/*
 * Copyright (c) 2020-2099 the original author or authors. All rights reserve.
 */
package org.tianyun.cloud.context;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * ApplicationContext
 *
 * @auther ebert_chan
 */
public class AppContext implements ApplicationContextAware, BeanDefinitionRegistryPostProcessor {

    /**
     * ApplicationContext
     */
    private static ApplicationContext context;

    /**
     * BeanDefinitionRegistry
     */
    private static BeanDefinitionRegistry registry;

    /**
     * ConfigurableListableBeanFactory
     */
    private static ConfigurableListableBeanFactory beanFactory;

    /**
     * 获取ApplicationContext
     *
     * @return ApplicationContext
     * @auther ebert_chan
     */
    public static ApplicationContext getApplicationContext() {
        return context;
    }

    /*
     * @see org.springframework.context.ApplicationContext#getBean(java.lang.Class)
     */
    public static <T> T getBean(Class<T> type) {
        return context.getBean(type);
    }

    /*
     * @see org.springframework.context.ApplicationContext#getBean(java.lang.String)
     */
    public static Object getBean(String beanName) {
        return context.getBean(beanName);
    }

    /**
     * 手动创建BeanDefinition
     *
     * @param beanName
     * @param beanClass
     * @param args
     * @auther ebert_chan
     */
    public static void registerBeanDefinition(String beanName, Class<?> beanClass, Object... args) {
        if (registry.containsBeanDefinition(beanName)) {
            return;
        }

        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(beanClass);
        for (Object arg : args) {
            beanDefinitionBuilder.addConstructorArgValue(arg);
        }
        BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
        registry.registerBeanDefinition(beanName, beanDefinition);
    }

    /**
     * 手动注册Bean
     *
     * @param beanName
     * @param singletonObject
     * @auther ebert_chan
     */
    public static void registerSingleton(String beanName, Object singletonObject) {
        beanFactory.registerSingleton(beanName, singletonObject);
    }

    /*
     * @see org.springframework.context.ApplicationContextAware#setApplicationContext (org.springframework.context.ApplicationContext)
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        AppContext.context = (ConfigurableApplicationContext) applicationContext;
    }

    /*
     * @see org.springframework.beans.factory.config.BeanFactoryPostProcessor# postProcessBeanFactory(org.springframework.beans.factory.config.
     * ConfigurableListableBeanFactory)
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        AppContext.beanFactory = beanFactory;
    }

    /*
     * @see org.springframework.beans.factory.support. BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry(org
     * .springframework.beans.factory.support.BeanDefinitionRegistry)
     */
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        AppContext.registry = registry;
    }

}
